/**
 * @file bsp_uart.c
 * @author fei_niao
 * @brief UART通信驱动模块
 * @version 1.3.0
 * @date 2025-05-20
 * @copyright Copyright (c) 2025 飞鸟
 *
 * @par 功能概述
 * + 提供UART外设初始化配置
 * + 支持DMA/中断两种传输模式
 * + 实现基本数据收发功能
 *
 * @par 典型工作流程
 * 1. BSP_USART_Init() -> 初始化串口硬件
 * 2. BSP_DMA_INIT()  -> 配置DMA通道
 * 3. 调用发送接口进行数据传输
 */

#include "bsp_uart.h"


/**
 * @brief UART外设初始化
 * @param dev UART设备配置结构体指针
 *
 * @details 初始化流程：
 * 1. 使能GPIO和USART时钟
 * 2. 配置TX/RX引脚模式
 * 3. 设置波特率等通信参数
 * 4. 配置中断优先级
 * 5. 使能外设
 *
 * @warning
 * - 需确保GPIO模式与硬件电路匹配
 */
void BSP_USART_Init(UART_Device_Typedef* dev) {
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    USART_InitTypeDef USART_InitStructure = {0};
    NVIC_InitTypeDef  NVIC_InitStructure = {0};

    dev->RCC_APB1PeriphClockCmd(dev->RCC_APB1Periph, ENABLE);
    dev->RCC_APB2PeriphClockCmd(dev->RCC_APB2Periph, ENABLE);

    GPIO_InitStructure.GPIO_Pin = dev->tx_pin;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = dev->gpio_tx_pin_mode;
    GPIO_Init(dev->port, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = dev->rx_pin;
    GPIO_InitStructure.GPIO_Mode = dev->gpio_rx_pin_mode;
    GPIO_Init(dev->port, &GPIO_InitStructure);


    USART_InitStructure.USART_BaudRate = dev->BaudRate;
    USART_InitStructure.USART_WordLength = dev->WordLength;
    USART_InitStructure.USART_StopBits = dev->StopBits;
    USART_InitStructure.USART_Parity = dev->Parity;
    USART_InitStructure.USART_HardwareFlowControl = dev->HardwareFlowControl;
    USART_InitStructure.USART_Mode = dev->Mode;

    USART_Init(dev->UARTx, &USART_InitStructure);

    USART_ITConfig(dev->UARTx, dev->USART_IT, ENABLE);


    NVIC_InitStructure.NVIC_IRQChannel = dev->NVIC_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = dev->NVIC_IRQChannelPreemptionPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = dev->NVIC_IRQChannelSubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = dev->NVIC_IRQChannelCmd;
    NVIC_Init(&NVIC_InitStructure);

    USART_Cmd(dev->UARTx, ENABLE);
    USART_DMACmd(dev->UARTx, dev->USART_DMAReq, ENABLE);
}


/**
 * @brief DMA通道初始化
 * @param UART_Device_DMA DMA配置结构体指针
 *
 * @details 配置要点：
 * 1. 设置外设/内存地址
 * 2. 配置数据传输方向
 * 3. 定义数据宽度和增量模式
 * 4. 设置缓冲区大小
 *
 * @note 典型应用场景：
 * - 接收：DMA_DIR_PeripheralToMemory
 * - 发送：DMA_DIR_MemoryToPeripheral
 */
void BSP_DMA_INIT(Device_DMA_Typedef* UART_Device_DMA) {
    UART_Device_DMA->RCC_AHBPeriphClockCmd(UART_Device_DMA->RCC_AHBPeriph, ENABLE);

    DMA_InitTypeDef DMA_InitStructure = {0};

    DMA_DeInit(UART_Device_DMA->DMAx_Channely);  // USART3_RX 对应 DMA1_Channel3
    DMA_InitStructure.DMA_PeripheralBaseAddr = UART_Device_DMA->DMA_PeripheralBaseAddr;
    DMA_InitStructure.DMA_MemoryBaseAddr = UART_Device_DMA->DMA_MemoryBaseAddr;
    DMA_InitStructure.DMA_DIR = UART_Device_DMA->DMA_DIR;  // 外设->内存
    DMA_InitStructure.DMA_BufferSize = UART_Device_DMA->DMA_BufferSize;
    DMA_InitStructure.DMA_PeripheralInc = UART_Device_DMA->DMA_PeripheralInc;
    DMA_InitStructure.DMA_MemoryInc = UART_Device_DMA->DMA_MemoryInc;
    DMA_InitStructure.DMA_PeripheralDataSize = UART_Device_DMA->DMA_PeripheralDataSize;
    DMA_InitStructure.DMA_MemoryDataSize = UART_Device_DMA->DMA_MemoryDataSize;
    DMA_InitStructure.DMA_Mode = UART_Device_DMA->DMA_Mode;  // 不连续传输
    DMA_InitStructure.DMA_Priority = UART_Device_DMA->DMA_Priority;
    DMA_InitStructure.DMA_M2M = UART_Device_DMA->DMA_M2M;
    DMA_Init(UART_Device_DMA->DMAx_Channely, &DMA_InitStructure);

    DMA_Cmd(UART_Device_DMA->DMAx_Channely, ENABLE);
}

#ifdef DMA_NOT_NEED
/**
 * @brief 阻塞式单字节发送
 * @param Byte 待发送数据
 *
 * @note 用于禁用DMA时的基本通信
 * @warning 会阻塞直到发送完成
 */
void uart_SendByte(uint8_t Byte)
{
    USART_SendData(USART3, Byte);
    while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}
/**
 * @brief 阻塞式数据块发送
 * @param Array 数据指针
 * @param Length 数据长度
 *
 * @note 每次发送前需检查TXE标志
 */
void uart_SendArray(uint8_t *Array, uint16_t Length)
{
    uint16_t i;
    for (i = 0; i < Length; i ++ )
    {
        uart_SendByte(Array[i]);
    }
}

#endif
